package pogvue.gui.menus;

import pogvue.analysis.AAFrequency;
import pogvue.analysis.AlignmentSorter;
import pogvue.gui.*;
import pogvue.gui.event.AlignViewportEvent;
import pogvue.gui.event.StatusEvent;

import java.awt.event.ActionEvent;
import java.util.Hashtable;
import java.util.Vector;

import javax.swing.*;

public class CalcMenu extends PanelMenu {

  private AutoConsensusAction autoconsensus;
  private ConsensusAction     consensus;
  private SortAction          pairIdSort;
  private SortAction          idSort;
  private SortAction          groupSort;
  private SortAction          treeSort;
  private RedundancyAction    remRedund;
  private PCAAction           pca;
  private AvTreeAction        averTree;
  private NeighbTreeAction    neighbTree;
  private AvTreeAction        averTree2;
  private NeighbTreeAction    neighbTree2;
  private ConservationAction  conservation;
  private RunCommandAction    runCommand;
  
  public CalcMenu(JPanel panel, AlignViewport av, Controller c) {
    super("Calc",panel,av,c);
  }

  protected void init() {
    consensus    = new ConsensusAction("Consensus");
    autoconsensus = new AutoConsensusAction("Autocalculate consensus",false);
  
    pairIdSort   = new SortAction("Sort by pairwise identity");
    idSort       = new SortAction("Sort by ID");
    groupSort    = new SortAction("Sort by group");
    treeSort     = new SortAction("Sort by tree order");
    remRedund    = new RedundancyAction("Remove redundancy");
    pca          = new PCAAction("Principal component analysis");
    averTree     = new AvTreeAction("Average distance tree using PID");
    neighbTree   = new NeighbTreeAction("Neighbour joining tree using PID");
    averTree2    = new AvTreeAction("Average distance tree using BLOSUM62");
    neighbTree2  = new NeighbTreeAction("Neighbour joining tree using BLOSUM62");

    averTree2.setScoreType("BL");
    neighbTree2.setScoreType("BL");

    conservation = new ConservationAction("Conservation");
  
    add(idSort);
    add(groupSort);
    add(treeSort);
    
    addSeparator();

    add(pca);

    addSeparator();

    add(averTree);
    add(neighbTree);

    add(averTree2);
    add(neighbTree2);

    //addSeparator();

    //add(conservation);

    //addSeparator();
    //add(runCommands);
  }
  class AutoConsensusAction extends JalToggleAction {
    public AutoConsensusAction(String name, boolean state) {
      super(name,state);
    }
    public void applyAction(ActionEvent evt) {
    }
  }

  class RunCommandAction extends JalAction {
    public RunCommandAction(String name) {
      super(name);
    }
    public void applyAction(ActionEvent evt) {
      //new CommandPopup(frame,av,controller,getName());
    }
  }

  class ConsensusAction extends JalAction {
    public ConsensusAction(String name) {
      super(name);
    }
    public void applyAction(ActionEvent evt) {
      System.out.println("Calc freq");

      Vector freq = AAFrequency.calculate(av.getAlignment().getSequences(),av.getStartRes(),av.getEndRes());

      for (int i = 0; i < freq.size(); i++) {
	Hashtable hash = (Hashtable)freq.elementAt(i);

	System.out.println("Count " + i + " " + hash.get("maxCount") + " " + hash.get("maxResidue"));
      }
    }
  }

  class SortAction extends JalAction {
    public SortAction(String name) {
      super(name);
    }
    public void applyAction(ActionEvent evt) {
      boolean error = false;
      if (name.equals("Sort by pairwise identity")) {
        controller.handleStatusEvent(new StatusEvent(this,"Sorting sequences by PID...",StatusEvent.INFO));
 
        System.out.println("NOTE: Sorts relative to FIRST sequence");
        AlignmentSorter.sortByPID(av.getAlignment(),av.getAlignment().getSequenceAt(0));

      } else if (name.equals("Sort by ID")) {
        controller.handleStatusEvent(new StatusEvent(this,"Sorting sequences by ID...",StatusEvent.INFO));
 
        AlignmentSorter.sortByID(av.getAlignment());

      } else if (name.equals("Sort by group")) {
        controller.handleStatusEvent(new StatusEvent(this,"Sorting sequences by group...",StatusEvent.INFO));
 
        AlignmentSorter.sortGroups(av.getAlignment());
        AlignmentSorter.sortByGroup(av.getAlignment());
      } else if (name.equals("Sort by tree order")) {
        if (av.getCurrentTree() != null) {
          controller.handleStatusEvent(new StatusEvent(this,"Sorting sequences by tree...",StatusEvent.INFO));
   
          AlignmentSorter.sortByTree(av.getAlignment(),av.getCurrentTree());
        } else {
          controller.handleStatusEvent(new StatusEvent(this,"No tree defined",StatusEvent.ERROR));
          error = true;
        }
      }
      if (!error) {
        controller.handleAlignViewportEvent(new AlignViewportEvent(this,av,AlignViewportEvent.ORDER));
        controller.handleStatusEvent(new StatusEvent(this,"done",StatusEvent.INFO));
      }
    }
  }

  class RedundancyAction extends JalAction {
    public RedundancyAction(String name) {
      super(name);
    }
    public void applyAction(ActionEvent evt) {
      controller.handleStatusEvent(new StatusEvent(this,"Creating redundancy chooser...",StatusEvent.INFO));
 
    }
  }

  class PCAAction extends JalAction {
    public PCAAction(String name) {
      super(name);
    }
    public void applyAction(ActionEvent evt) {
      controller.handleStatusEvent(new StatusEvent(this,"Starting PCA calculation...",StatusEvent.INFO));
 
      PCAThread pcat = new PCAThread(panel,av,controller,av.getAlignment().getSequences());
      pcat.start();
    }
  }

  class AvTreeAction extends TreeAction {
    public AvTreeAction(String name) {
      super(name);
    }
    protected  String getTitle() {
        return "Average distance tree using PID";
    }
    protected  String getType() {
      return "AV";
    }
  }

  class NeighbTreeAction extends TreeAction {
    public NeighbTreeAction(String name) {
      super(name);
    }
    protected  String getTitle() {
        return "Neighbour joining tree using PID";
    }
    protected  String getType() {
      return "NJ";
    }
  }

  abstract class TreeAction extends JalAction {
      String type      = "AV";
      String scoreType = "PID";

    public TreeAction(String name) {
      super(name);
    }
    public void applyAction(ActionEvent evt) {
	TreeThread tt;

	if (av.getSelection() != null && av.getSelection().size() > 3) {
	    Vector seqs = av.getSelection().asVector();
	    tt = new TreeThread(controller,av,seqs, getType(),getScoreType(),av.getStartRes(),av.getEndRes());
	} else {
	    tt = new TreeThread(controller,av,av.getAlignment().getSequences(), getType(), getScoreType(),av.getStartRes(),av.getEndRes());
      }
      controller.handleStatusEvent(new StatusEvent(this,"Calculating " + getType() + " tree",StatusEvent.INFO));
      tt.start(); 
    }

    protected abstract String getTitle();
    protected abstract String getType();
      protected void setType(String type) {
	  this.type = type;
      }
      void setScoreType(String type) {
	  this.scoreType = type;
      }
      String getScoreType() {
	  return scoreType;
      }
  }
 

  class ConservationAction extends JalAction {
    public ConservationAction(String name) {
      super(name);
    }
    public void applyAction(ActionEvent evt) {
    }
  }
}
